Cerline Jeremy
Cerline Jeremy

Reputation: 1

why FormData not sent to server, the server receive empty request using put with expo image picker

It seems like the backend is receiving an empty request (Request Data: ) despite my app sending the data. This indicates that the FormData is not being sent properly or is empty when it reaches the backend.Also when i send data without file/logo and the multpart form data header they works here my client and server side code

  public function update(Request $request, $id)
{
    // Log incoming data for debugging
    \Log::info('Request Data:', $request->all());
    //i receive [2025-01-31 10:06:54] local.INFO: Request Data: 

    // Validate incoming data
    $validator = Validator::make($request->all(), [
        'name' => 'required|string|max:255',
        'logo' => 'nullable|image|mimes:jpeg,png,jpg|max:526',  // Un-commented logo validation
        'location' => 'nullable|string|max:255',
        'phone_number' => 'nullable|regex:/^\d{10,13}$/',
        'email' => 'nullable|string|email|max:255',
    ]);

    if ($validator->fails()) {
        return response()->json($validator->errors(), 422); // Validation error
    }

    // Fetch the shop from the authenticated user's shops
    $shop = Auth::user()->shops()->where('id', $id)->first();

    // Check if shop exists and belongs to the authenticated user
    if (!$shop) {
        return response()->json(['message' => 'Shop not found!'], 404);
    }

    // Initialize validated data
    $validated = $validator->validated();

    // Handle the logo upload if it exists
    if ($request->hasFile('logo')) {
        // Get the logo file from the request
        $logo = $request->file('logo');

        // Ensure the file is valid
        if ($logo->isValid()) {
            // Generate a unique name for the logo file
            $logoName = time() . '.' . $logo->getClientOriginalExtension();

            // Store the logo in public storage and get its path
            $logoPath = $logo->storeAs('public/logos', $logoName);

            // Update the validated data with the logo path (relative to public storage)
            $validated['logo'] = 'storage/logos/' . $logoName;
        } else {
            return response()->json(['message' => 'Logo upload failed!'], 500);
        }
    }

    // Update the shop with validated data
    $shop->update($validated);

    // Return a successful response with updated shop information
    return response()->json([
        'message' => 'Shop updated successfully',
        'shop' => $shop,
    ]);
}

While frontend look like

    // Open the modal to edit shop details
  const openEditModal = (shop) => {
    setShopToEdit(shop);
    setUpdatedShopDetails({
      name: shop.name,
      location: shop.location,
      phone_number: shop.phone_number,
      email: shop.email
    });
    setErrors({});
    setSelectedLogo(null); // Reset selected logo when opening the edit modal
    setIsModalVisible(true);
  };

  // Pick an image for the logo
  const pickImage = async () => {
    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: 'images',
      allowsEditing: true,
      quality: 1,
    });

    if (!result.canceled) {
      setSelectedLogo(result.assets[0]); // Store the selected logo image
    }
  };

  // Handle updating the shop
  const handleUpdateShop = async () => {
    const token = await getAuthToken();
    if (!token || !shopToEdit) return;

    let validationErrors = {};
    if (!updatedShopDetails.name) validationErrors.name = 'Name is requiredx.';

    if (Object.keys(validationErrors).length > 0) {
      setErrors(validationErrors);
      Toast.show({
        type: 'error',
        text1: 'Please fill out all required fields',
        position: 'bottom',
        visibilityTime: 2000,
        autoHide: true,
      });
      return;
    }

    try {
      const formData = new FormData();
      formData.append('name', updatedShopDetails.name);
      formData.append('location', updatedShopDetails.location);
      formData.append('phone_number', updatedShopDetails.phone_number);
      formData.append('email', updatedShopDetails.email);

      // If a logo was selected, append it to the FormData
      if (selectedLogo) {
        const logo = {
          uri: selectedLogo.uri,
          type: selectedLogo.mimeType || 'image/png',
          name: selectedLogo.fileName || 'logo.png',
        };
      
        console.log('Appending logo:', logo);  // Log the logo details to check
      
        formData.append('logo', {
          uri: logo.uri,
          type: logo.type,
          name: logo.name,
        });
      }
      formData.forEach((value, key) => {
        console.log('check if is key to value pair:', key, value);
      });
      //console.log('data:', formData);
      await api.put(`/shops/${shopToEdit.id}`, formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });

      setShops(shops.map(shop => {
        if (shop.id === shopToEdit.id) {
          return { ...shop, ...updatedShopDetails }; 
        }
        return shop;
      }));

      Toast.show({
        type: 'success',
        text1: 'Shop updated successfully',
        position: 'bottom',
        visibilityTime: 2000,
        autoHide: true,
      });
      setIsModalVisible(false);
    } catch (error) {
      if (error.response) {
        const { status, data } = error.response;
        console.error('Error updating shop:', status, data);
        Toast.show({
          type: 'error',
          text1: 'Error updating shop',
          position: 'bottom',
          visibilityTime: 2000,
          autoHide: true,
        });
      } else {
        // Handle the case where there's no response (network issues or something else)
        console.error('Network or other error:', error);
        Toast.show({
          type: 'error',
          text1: 'Network error. Please try again later.',
          position: 'bottom',
          visibilityTime: 2000,
          autoHide: true,
        });
      }
    }
  };

the log look like

    LOG  check if is key to value pair: name sukus.
 (NOBRIDGE) LOG  check if is key to value pair: location Dubai
 (NOBRIDGE) LOG  check if is key to value pair: phone_number null
 (NOBRIDGE) LOG  check if is key to value pair: email [email protected]
 (NOBRIDGE) LOG  check if is key to value pair: logo {"name": "2469b768-2f52-40aa-952f-f7995bd82cc4.png", "type": "image/png", "uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fbizman-9889f099-e502-4c1d-9bf1-c4c27eb5030a/ImagePicker/2469b768-2f52-40aa-952f-f7995bd82cc4.png"}
 (NOBRIDGE) ERROR  Error updating shop: 422 {"name": ["The name field is required."]}

This happen while uploading image but if i remove code for images and use Accept:application/json it works

Upvotes: 0

Views: 33

Answers (0)

Related Questions