Как обновить файлы с помощью Ax ios и React - PullRequest
0 голосов
/ 27 апреля 2020

Я создал API с сообщениями / статьями, и теперь я работаю над интерфейсом. У меня проблема с загрузкой новой фотографии для уже существующего сообщения. Я попытался два наиболее распространенных метода для фотографии, formData и JSON Base64. Я получаю одно и то же сообщение об ошибке для обоих методов, Please upload a file, code: 400. Я не уверен, где я ошибся, поэтому я предоставлю все соответствующие файлы.

статьи. js (сервер)

exports.articlePhotoUpload = asyncHandler(async (req, res, next) => {
    const article = await Article.findById(req.params.id);

    if (!article) {
        return next(
            new ErrorResponse(`Article not found with id of ${ req.params.id }`, 404)
        );
    }

    //Make sure user is article owner || make sure user is admin
    if (article.user.toString() !== req.user.id || req.user.role !== 'admin') {
        return next(
            new ErrorResponse(
                `User ${ req.user.id } is not authorized to update this article`,
            )
        )
    }

    if (!req.files) {
        return next(new ErrorResponse(`Please upload a file`, 400))
    }

    const file = req.files.file;

    // Confirm the image is a photo
    if (!file.mimetype.startsWith('image')) {
        return next(new ErrorResponse(`Please upload an image file`, 400))
    }

    // Check File Size
    if (file.size > process.env.MAX_FILE_UPLOAD) {
        return next(
            new ErrorResponse(`Please upload an image less than ${ MAX_FILE_UPLOAD }`, 400)
        )
    }

    // Create custom filename
    file.name = `photo_${ article._id }${ path.parse(file.name).ext }`;

    file.mv(`${ process.env.FILE_UPLOAD_PATH }/${ file.name }`, async err => {
        if (err) {
            console.log(err);
            new ErrorResponse(`Problem with file upload`, 500);
        }

        await Article.findByIdAndUpdate(req.params.id, { photo: file.name });

        res.status(200).json({
            success: true,
            data: file.name
        });

    });

});

^ вышеупомянутая функция - это то, где сообщение об ошибке запускается на стороне сервера.

ax ios. js (на стороне клиента)

...
axios.defaults.baseURL = 'http://<<ip address>>/api/v1';
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('auth');
axios.defaults.headers.post['Content-Type'] = 'application/json';


export const uploadPhoto = (id, data) => {
    return axios.put(`/articles/${ id }/photo`, {
        data
    })
}
...

^ У меня есть ощущение, что я мог бы лучше отформатировать эту экспортированную функцию. Я мог бы что-то здесь упустить.

UploadPhoto.jsx (JSON Попытка)

const UploadPhoto = (props) => {
    const { register, handleSubmit } = useForm();
    const { state } = useStateMachine(updateAction);
    const [file, setFile] = useState(null);
    const [filename, setFilename] = useState(null);

    const onSubmit = async () => {
        const toBase64 = file => new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => resolve(reader.result);
            reader.onerror = error => reject(error);
            console.log(reader.result)
        });

        const data = {
            title: filename,
            file: await toBase64(file),
        }

        uploadPhoto(`5ea5e73044718d0b2c2ae5df`, data)
            .then(res => console.log(res))
            .catch(err => console.log(err.response.data.error))
    }

    const handleChange = (e) => {
        setFile(e.target.files[0]);
        setFilename(e.target.files[0].name);
    }

    return (
        <form onSubmit={handleSubmit(onSubmit)}>
            <h2>Cover Image</h2>
            <label>
                Select A File:
            </label>
            <img id="image" src="" alt="" />
            <input
                type="file"
                name="photo"
                ref={register}
                defaultValue={state.data.photo}
                onChange={handleChange}

            />
            <label htmlFor="">
                Filename
            </label>
            <input type="submit" />
        </form>
    )
}

export default withRouter(UploadPhoto);

UploadPhoto.jsx (попытка формирования данных)

const onSubmit = () => {
        const formData = new FormData();
        formData.append("file", file);
        console.log(file)

        uploadPhoto(`5ea5e73044718d0b2c2ae5df`, formData)
            .then(res => console.log(res))
            .catch(err => console.log(err.response.data.error))
    }

Это мой первый раз, когда я создаю свой собственный API, именно поэтому я поместил здесь код сервера. Однако я на 90% уверен, что совершаю ошибку на стороне клиента, скорее всего, в файле ax ios. js.

1 Ответ

0 голосов
/ 27 апреля 2020

Давайте попробуем этот пример:

const fileUpload = require('express-fileupload');
const app = express();

// enable files upload -- this should also make 'req.files' accessible
app.use(fileUpload({
    createParentPath: true
}));

Добавьте это в начале инициализации вашего сервера. После этого ваш нормальный код должен попытаться получить доступ к req.files, как это должно быть заполнено при запросах на загрузку файлов. Вам нужно будет установить модуль express -fileupload, прежде чем использовать его в коде -> npm i express-fileupload

(Источник: https://attacomsian.com/blog/uploading-files-nodejs-express)

...