Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Дружба трех друзей React, Delphi, HP LJ M127
Сегодня я расскажу вам историю дружбы трех друзей или если по простому то как я , мне пришла идея подружить веб с железом.
Начну наверное с того что все началось с написания софтверного приложения на delphi для сканирования документов и сохранения их blob данных в БД MSSQL SERVER 20212, ниже я приведу скриншот этого приложения, но как говорится в заголовке моей статьи сегодня речь пойдет, о другом приложении
Вообще идея пришла с того что хотелось сделать приложение, которое можно было запускать на любом компьютере, но тут как раз и появилась первая проблема, reactjs как и все веб фреймворки не работает с железом с драйверами, и тут на помощь пришел мои опыт работы с высокоуровневым языком программирования Delphi
Приложение на React
Представляю вашему вниманию страницу входа авторизации
Авторизация у меня по сути построена на двух функциях, одна функция это проверка авторизовался ли ранее этот пользователь, а вторая функцию уже авторизует пользователя
ReallyAut=()=>
{
axios.get(Conf.API_URL+'user/really_aut/'+localStorage.getItem('hash'))
.then(res => {
const data= res.data;
let autentificate = data.autentificate;
this.setState({autentificate : autentificate.success});
this.props.aut(data.data.hash,data.success,data.data.username);
this.props.autentificate(autentificate);
})
}
Данная функция как раз и занимается проверкой авторизован ли пользователь, эту функцию я вызываю в жизненном цикле react в ComponentDidMount ( эта функция выполняется после добавления объекта в дерево DOM) и конечно же я использую hash значения для работы с авторизациями
Autorize = (event) => {
event.preventDefault();
let passwd = this.passwdRef.current.value;
let login = this.loginRef.current.value;
Toast.loading('Ожидание ответа....');
axios.get(Conf.API_URL+'user/autorize/'+login+'/'+passwd)
.then(res => {
const data = res.data;
Toast.hide();
if(data.success){
this.props.aut(data.token,data.success,data.name);
localStorage.setItem('hash',data.token);
localStorage.setItem('userName',data.token);
} else
{
NotificationManager.error('Неверный логин или пароль, повторите ввод','Ошибка авторизации',3000);
}
}).catch(err => {
if (err.response) {
// client received an error response (5xx, 4xx)
} else if (err.request) {
// client never received a response, or request never left
} else {
// anything else
}
NotificationManager.error('Нет доступа....','Ошибка',3000);
console.log(err);
Toast.hide();
});
}
Ну вот мы и добрались до второй функции которая авторизует нас на сервере и выдает нам token
Главная форма имеет следующий вид, и как видно из скриншота позволяет нам в быстром наборе, выбирать заказчика и исполнителя, но основной функционал заключается в другом, а именно в сканировании и сохранении документа, побочные функции это удаление, перемещение , добавление сканированных документов
В общем уже заполненная форма сканированными документами, как видно на скриншоте их можно перемещать удалять
Как в общем производится сканирование, тут в принципе все просто, в программе на DELPHI которая сидит в трее заключена вся сила, а именно это связь со сканером HP LJ M127 , приложение закрепляет на порту слушатель , теперь перейдем к приложению на Delphi
Приложение Delphi
Опишем основные объекты, один из которых это объект который хранит в себе информацию об отсканированных изображения, тут основная хитрость в том чтобы хранить изображение в зашифрованном виде в виде строки чтобы удобно ее передавать и хранить
type
TScanImage = class(Tobject)
public
Image: TBitmap;
thumbnail: TJPEGImage;
StreamBitmap: TMemoryStream;
base64_image: String;
sended: Byte;
heigh: Integer;
width: Integer;
date_scan: TDateTime;
constructor Create(zimg: TBitmap; zh, zw: Integer; zds: TDateTime);
end;
Второй объект нужен для информирования нашего веб приложения о текущих задачах которые выполняет наше приложение, событии всего несколько
Событии нету
Сканирование Документа
Поворот картинки
Конвертация в PDF
Сохранение на сервер
type
TEvents = class(Tobject)
public
procedure SetEvent(EventCode: Byte; EventStatus: Byte;
EventData: TJSONArray);
procedure SetEventName(EventName: String; EventCode: Byte);
procedure SetStatusEvent(EventStatus: Byte);
procedure SetEventData(EventData: TJSONArray);
function GetEvent: TJSONObject;
private
constructor Create();
protected
event_name: String;
event_code: Byte;
event_status: Byte;
event_date: Int64;
event_data: TJSONArray;
event_message: String;
end;
То есть сам принцип дружбы заключается в звене которое выполняет наше приложение на Delphi , это происходит так
1. Веб приложение на React посредством http запросов (через axios) дает команду на сканирование документа, приложение на Delphi слушает порт и получает команду начинает выполнять и записывает в события что происходит в данный момент в приложении на delphi
2. Веб приложение через определенный промежуток запрашивает статус задачи которая выполняется или уже выполнилась
3. Приложение на Delphi когда завершила сканирование документа (Это может быть и автоподачик и ручное сканирование) записывает в статус события объекты которые отсканировала и при запросе от веб приложения их отдает
Вернемся к веб приложению на ReactJS
На данном скриншоте представлены документы которые уже отсканированы и их можно просмотреть, удалить
Просмотр документа с возможностью его загрузки
Удаление документа